//
//  BC_SplitPoint.m
//  CocOth
//
//  Created by BrunoCausse on 25/01/11.
//  Copyright 2011 poulailler cie. All rights reserved.
//

#import "BC_SplitPoint.h"

#import "BC_Const.h"
#import "BC_Board.h"
#import "BC_Move.h"
#import "BC_ZooRequest.h"


@implementation BC_SplitPoint

@synthesize parent;
@synthesize alpha, beta;
@synthesize bestscore, time;
@synthesize bestMove, bestPV;
@synthesize stop;
@synthesize cut;
@synthesize descriptionForZoo;

- (id)initWithBoard:(BC_Board *)aBoard
			  moves:(NSMutableArray *)arrayMoves
			  alpha:(NSInteger)low
			   beta:(NSInteger)high
				cut:(NSUInteger)selectivity
			 parent:(BC_SplitPoint *)sp
{
	self = [super init];
	if (self) {
		
		parent = sp; //simple assignation
		
		board = [aBoard retain];
		descriptionForZoo = [[board descriptionForZoo] retain];
		
		moves = [arrayMoves retain];
		nWorkers = [moves count];
		
		
		NSAssert(low < high, @"splitpoint low >= high");
		
		alpha	= low;
		beta	= high;
		cut		= selectivity;
		
		bestscore = UNDEFSCORE;
		time      = UNDEFTIME;
		bestPV    = nil;
		
		myCondition = [[NSCondition alloc] init];
		
		registerLock = [[NSLock alloc] init];
		stop  = 0;
		children = [[NSMutableArray alloc] initWithCapacity:32]; 
				
	}
	
	return self;
}

- (void)dealloc
{
	[children release];
	[registerLock release];
	
	[myCondition release];
	[bestPV release];
	[moves release];
	[descriptionForZoo release];
	[board release];
	
	[super dealloc];
}

- (BC_Move *)nextMove
{
	BC_Move *move = nil;
	
	@synchronized(self) {
		
		int nMoves = [moves count];
		
		if (nMoves > 0) {
						
			move = [[moves objectAtIndex:0]retain];
			
			[moves removeObjectAtIndex:0];
			
		}
	}
	
	return [move autorelease];
}

/*
 fixe la variable partagée Stop a YES
 informe le sous arbre (recursif)
 */
- (void)should_stop
{
	@synchronized(self) {
		
		//prendre le nutex
		[registerLock lock];
		stop = YES;
				
		//informe la descendance (splitpoint ou request)
		for(id child in children) {
			[child should_stop];
		}
		
		//relache le mutex
		[registerLock unlock];
		
	}
}
		


- (void)wait
{
	[myCondition lock];
	NSAssert(nWorkers >= 0, @"BUG: nWorkers < 0");
	if(nWorkers > 0) {
		[myCondition wait];
	}
	[myCondition unlock];
}


- (void)signal
{
	[myCondition lock];
	NSAssert(nWorkers >= 0, @"BUG: nWorkers < 0");

	nWorkers--;
	
	if(nWorkers <= 0) {
		[myCondition signal];
	}
	[myCondition unlock];
}

- (BOOL)add:(id)child
{
	BOOL ok = NO;
	//si le noeuds doit stopper
	//refuser le children
	//non synchro
	if(!stop) {
		[registerLock lock];
		//idem mais synchro
		if(!stop) {
			[children addObject:child];
			ok = YES;
		}
		[registerLock unlock];
	}
	return ok;
}

- (void)remove:(id)child
{
	[registerLock lock];
	[children removeObject:child];
	[registerLock unlock];
}




@end
